package com.dhq.myapp.util

import android.content.Context
import android.os.Environment
import android.util.Base64
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.nio.charset.Charset

/**
 * DESC
 * Created by DHQ on 2025/10/15.
 */
object FileUtil {

    val logFileName = "log.txt"

    @JvmStatic
    fun getLogInfo(context: Context):String{
        val filePath: String = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)?.absolutePath+ File.separator+logFileName;
        val file = File(filePath)
        if (!file.exists()){
            return "";
        }
        return readText(filePath)!!
    }

    @JvmStatic
    fun writeLogInfo(context: Context,content:String):Boolean{
        val filePath: String = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)?.absolutePath+ File.separator+logFileName;
        return appendText(filePath,content);
    }

    /**
     * 获取语音文件的保存路径
     */
    @JvmStatic
    fun getVoicePath(context: Context):String{
        val voiceFilePathName = "${System.currentTimeMillis()}.pcm"
        val filePath: String = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)?.absolutePath+ File.separator + "voice.pcm";
        return filePath;
    }

    /**
     * 获取语音文件的保存路径
     */
    @JvmStatic
    fun getVoiceFilePath(context: Context):String{
        val voiceFilePathName = "${System.currentTimeMillis()}.pcm"
        val filePath: String = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)?.absolutePath+ File.separator + "voice" + File.separator +voiceFilePathName;
        createFile(filePath)
        return filePath;
    }

    @JvmStatic
    fun writeByteFile(filePath: String, byteArray: ByteArray) {
        FileOutputStream(File(filePath), true).use { fos ->
            // 注意这里的 true 表示追加模式
            fos.write(byteArray)
        }
    }

    @JvmStatic
    fun getVoiceFileData(filePath: String) : String{
        val file = File(filePath)
        val allBytes: ByteArray = file.readBytes() // 一次性读取所有字节
        return convertAudioByteArrayToBase64(allBytes)
    }

    /**
     * 将ByteArray数组数据转换成字符串数据
     */
    fun convertAudioByteArrayToBase64(audioData: ByteArray): String {
        return Base64.encodeToString(audioData, Base64.DEFAULT)
    }



    @JvmStatic
    fun getFileName(path: String): String {
        // 使用trim()移除首尾的空白字符（包括换行符）
        val cleanPath = path.trim()
        val fileName = File(cleanPath).name
        return fileName;
    }


    /**
     * 创建文件（如果不存在）
     * @param filePath 文件路径
     * @return Boolean 是否创建成功或已存在
     */
    @JvmStatic
    fun createFile(filePath: String): Boolean {
        return try {
            val file = File(filePath)
            if (!file.exists()) {
                // 确保父目录存在
                file.parentFile?.mkdirs()
                file.createNewFile()
            } else {
                true
            }
        } catch (e: IOException) {
            e.printStackTrace()
            false
        }
    }

    /**
     * 创建多级目录
     * @param dirPath 目录路径
     * @return Boolean 是否创建成功
     */
    @JvmStatic
    fun createDirs(dirPath: String): Boolean {
        return try {
            val dir = File(dirPath)
            dir.mkdirs()
        } catch (e: Exception) {
            e.printStackTrace()
            false
        }
    }

    /**
     * 写入文本内容（覆盖模式）
     * @param filePath 文件路径
     * @param content 文本内容
     * @param charset 字符编码（默认UTF-8）
     * @return Boolean 是否写入成功
     */
    @JvmStatic
    fun writeText(filePath: String, content: String, charset: Charset = Charsets.UTF_8): Boolean {
        return try {
            if (!createFile(filePath)) return false
            File(filePath).writeText(content, charset)
            true
        } catch (e: IOException) {
            e.printStackTrace()
            false
        }
    }

    /**
     * 追加文本内容
     * @param filePath 文件路径
     * @param content 要追加的文本内容
     * @param charset 字符编码（默认UTF-8）
     * @return Boolean 是否追加成功
     */
    @JvmStatic
    fun appendText(filePath: String, content: String, charset: Charset = Charsets.UTF_8): Boolean {
        return try {
            if (!createFile(filePath)) return false
            File(filePath).appendText(content, charset)
            true
        } catch (e: IOException) {
            e.printStackTrace()
            false
        }
    }

    /**
     * 读取文本内容
     * @param filePath 文件路径
     * @param charset 字符编码（默认UTF-8）
     * @return String? 文件内容（失败返回null）
     */
    @JvmStatic
    fun readText(filePath: String, charset: Charset = Charsets.UTF_8): String? {
        return try {
            val file = File(filePath)
            if (!file.exists() || file.isDirectory) return null
            file.readText(charset)
        } catch (e: IOException) {
            e.printStackTrace()
            null
        }
    }

    /**
     * 读取文件为字节数组
     * @param filePath 文件路径
     * @return ByteArray? 字节数组（失败返回null）
     */
    @JvmStatic
    fun readBytes(filePath: String): ByteArray? {
        return try {
            val file = File(filePath)
            if (!file.exists() || file.isDirectory) return null
            file.readBytes()
        } catch (e: IOException) {
            e.printStackTrace()
            null
        }
    }

    /**
     * 写入字节数组
     * @param filePath 文件路径
     * @param data 字节数组
     * @return Boolean 是否写入成功
     */
    @JvmStatic
    fun writeBytes(filePath: String, data: ByteArray): Boolean {
        return try {
            if (!createFile(filePath)) return false
            File(filePath).writeBytes(data)
            true
        } catch (e: IOException) {
            e.printStackTrace()
            false
        }
    }

    /**
     * 复制文件
     * @param sourcePath 源文件路径
     * @param destPath 目标文件路径
     * @param overwrite 是否覆盖已存在文件
     * @return Boolean 是否复制成功
     */
    @JvmStatic
    fun copyFile(sourcePath: String, destPath: String, overwrite: Boolean = true): Boolean {
        return try {
            val sourceFile = File(sourcePath)
            val destFile = File(destPath)

            if (!sourceFile.exists() || sourceFile.isDirectory) return false
            if (destFile.exists() && !overwrite) return false

            // 确保目标目录存在
            destFile.parentFile?.mkdirs()

            // 使用NIO零拷贝技术提高大文件复制效率
            FileInputStream(sourceFile).channel.use { sourceChannel ->
                FileOutputStream(destFile).channel.use { destChannel ->
                    sourceChannel.transferTo(0, sourceChannel.size(), destChannel)
                }
            }
            true
        } catch (e: IOException) {
            e.printStackTrace()
            false
        }
    }

    /**
     * 移动文件/重命名
     * @param sourcePath 源路径
     * @param destPath 目标路径
     * @param overwrite 是否覆盖已存在文件
     * @return Boolean 是否移动成功
     */
    @JvmStatic
    fun moveFile(sourcePath: String, destPath: String, overwrite: Boolean = true): Boolean {
        return try {
            val sourceFile = File(sourcePath)
            val destFile = File(destPath)

            if (!sourceFile.exists()) return false
            if (destFile.exists() && !overwrite) return false

            // 确保目标目录存在
            destFile.parentFile?.mkdirs()

            if (sourceFile.renameTo(destFile)) {
                true
            } else {
                // 如果renameTo失败，尝试复制后删除
                if (copyFile(sourcePath, destPath, overwrite)) {
                    deleteFile(sourcePath)
                } else {
                    false
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
            false
        }
    }

    /**
     * 删除文件
     * @param filePath 文件路径
     * @return Boolean 是否删除成功
     */
    @JvmStatic
    fun deleteFile(filePath: String): Boolean {
        return try {
            val file = File(filePath)
            if (file.exists() && file.isFile) {
                file.delete()
            } else {
                false
            }
        } catch (e: Exception) {
            e.printStackTrace()
            false
        }
    }

    /**
     * 递归删除目录
     * @param dirPath 目录路径
     * @return Boolean 是否删除成功
     */
    @JvmStatic
    fun deleteDir(dirPath: String): Boolean {
        return try {
            val dir = File(dirPath)
            if (dir.exists() && dir.isDirectory) {
                dir.deleteRecursively()
            } else {
                false
            }
        } catch (e: Exception) {
            e.printStackTrace()
            false
        }
    }

    /**
     * 获取文件大小
     * @param filePath 文件路径
     * @return Long 文件大小（字节），-1表示文件不存在
     */
    @JvmStatic
    fun getFileSize(filePath: String): Long {
        return try {
            val file = File(filePath)
            if (file.exists() && file.isFile) {
                file.length()
            } else {
                -1
            }
        } catch (e: Exception) {
            e.printStackTrace()
            -1
        }
    }

    /**
     * 获取目录下所有文件
     * @param dirPath 目录路径
     * @param isRecursive 是否递归获取子目录文件
     * @param filter 文件过滤器（可选）
     * @return List<File> 文件列表
     */
    @JvmStatic
    fun listFiles(dirPath: String, isRecursive: Boolean = false, filter: ((File) -> Boolean)? = null): List<File> {
        return try {
            val dir = File(dirPath)
            if (!dir.exists() || !dir.isDirectory) return emptyList()

            if (isRecursive) {
                dir.walk()
                    .filter { it.isFile }
                    .filter { filter?.invoke(it) ?: true }
                    .toList()
            } else {
                dir.listFiles()
                    ?.filter { it.isFile }
                    ?.filter { filter?.invoke(it) ?: true }
                    ?: emptyList()
            }
        } catch (e: Exception) {
            e.printStackTrace()
            emptyList()
        }
    }

    /**
     * 检查文件是否存在
     * @param filePath 文件路径
     * @return Boolean 是否存在
     */
    @JvmStatic
    fun exists(filePath: String): Boolean {
        return File(filePath).exists()
    }

    /**
     * 获取文件扩展名
     * @param filePath 文件路径
     * @return String 文件扩展名（不含点）
     */
    @JvmStatic
    fun getFileExtension(filePath: String): String {
        return try {
            val fileName = File(filePath).name
            val dotIndex = fileName.lastIndexOf('.')
            if (dotIndex > 0 && dotIndex < fileName.length - 1) {
                fileName.substring(dotIndex + 1)
            } else {
                ""
            }
        } catch (e: Exception) {
            ""
        }
    }


}